package com.jinxiangyang.aop;

import com.jinxiangyang.annotation.OperateLog;
import com.jinxiangyang.domain.OperLog;
import com.jinxiangyang.service.OperLogService;
import com.jinxiangyang.utils.AddressUtils;
import com.jinxiangyang.utils.IpUtils;
import com.jinxiangyang.utils.ServletUtils;
import com.jinxiangyang.utils.StringUtils;
import com.jinxiangyang.utils.enums.BusinessType;
import com.jinxiangyang.utils.enums.OperatorType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * @author jinxiangyang
 * @date 2023/8/16 14:41
 * @description TODO
 **/

@Aspect
@Component
@Slf4j
public class LogAop {



    @Autowired
    private OperLogService operLogService;


    @Pointcut("@annotation(com.jinxiangyang.annotation.OperateLog)")
    public void pointCut(){
    }




    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
        String signature = joinPoint.getSignature().getName();
        Class<?> aClass = joinPoint.getTarget().getClass();
        Class<?>[] par=((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        Method objMethod=aClass.getMethod(signature, par);
        OperateLog annotation = objMethod.getAnnotation(OperateLog.class);
        BusinessType businessType = annotation.businessType();
        OperatorType operatorType = annotation.operatorType();
        String title = annotation.title();
        String ipAddr = IpUtils.getIpAddr();
        OperLog operLog = new OperLog();
        operLog.setOperatorType(operatorType.getCode());
        operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
        operLog.setOperIp(ipAddr);
        operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
        operLog.setMethod(objMethod.getName());
        operLog.setOperTime(new Date());
        operLog.setBusinessType(businessType.getId());
        operLog.setOperParam(Arrays.toString(joinPoint.getArgs()));
        operLog.setTitle(title);
        operLog.setOperLocation(AddressUtils.getRealAddressByIP(ipAddr));
        log.info("执行模块:{}",title);
        log.info("执行方法:{},====>{}",signature,joinPoint.getArgs());
        Object proceed = null;
        long millis = System.currentTimeMillis();
        try {
            proceed = joinPoint.proceed();
            log.info("执行方法:{}",signature);
            log.info("执行方法:{},< ===== {}",signature,proceed);
            operLog.setJsonResult(proceed.toString().substring(1, proceed.toString().length()));
        } catch (Throwable e) {
            log.error(e.getMessage());
            operLog.setStatus(1);
            operLog.setErrorMsg(e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
        long stop = System.currentTimeMillis();

        log.info("执行方法:{},消耗时间:{}",signature,stop-millis);
        operLog.setCostTime(stop-millis);
        operLogService.save(operLog);
        return  proceed;
    }
}
